package com.tarena.lbs.basic.web.service;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.github.pagehelper.PageInfo;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.basic.web.repository.AdminRepository;
import com.tarena.lbs.basic.web.repository.BusinessRepository;
import com.tarena.lbs.basic.web.utils.UserPrincipleThreadLocal;
import com.tarena.lbs.common.passport.encoder.JwtEncoder;
import com.tarena.lbs.common.passport.enums.Roles;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.common.security.utils.LbsSecurityContenxt;
import com.tarena.lbs.pojo.basic.param.AdminParam;
import com.tarena.lbs.pojo.basic.po.AdminPO;
import com.tarena.lbs.pojo.basic.po.BusinessPO;
import com.tarena.lbs.pojo.basic.query.AdminQuery;
import com.tarena.lbs.pojo.basic.vo.AdminVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class AdminService {

    @Autowired
    private JwtEncoder<UserPrinciple> jwtEncoder;
    @Autowired
    private AdminRepository adminRepository;
    @Autowired
    private BusinessRepository businessRepository;

    /**
     * 获取当前登录用户详情
     * @return
     * @throws BusinessException
     */
    public AdminVO detail() throws BusinessException {
        //1.使用解析器解析jwt 拿到userPrinciple
        //UserPrinciple userPrinciple =  jwtEncoder.getLoginFromToken(jwt, UserPrinciple.class);
        // 2.判断userPrinciple是否为空
        //if (userPrinciple==null){
            //log.error("jwt解析失败");
            //throw new BusinessException("-2","jwt解析失败");
        //}
        //UserPrinciple userPrinciple = UserPrincipleThreadLocal.get();
        UserPrinciple userPrinciple = LbsSecurityContenxt.getLoginToken();
        log.info("从线程上游的过滤器拿到存储数据:{}",userPrinciple);
        //有可能过滤器没有成功解析jwt 有可能请求没有携带jwt
        if (userPrinciple==null){
            //业务异常
            throw new BusinessException("-2","用户认证解析失败");
        }
        // 3.根据userPrinciple的id查询adminPO
        Integer adminId = userPrinciple.getId();
        AdminPO po = adminRepository.getAdminById(adminId);
        // 4.转化vo
        if (po!=null){
            //po查询到的adminPO不为空，前端展示详情时候，密码不需要展示
            po.setAccountPassword(null);
            AdminVO vo = new AdminVO();
            BeanUtils.copyProperties(po,vo);
            return vo;
        }
        return new AdminVO();
    }

    /**
     * 分页查询账号列表
     * @param query
     * @return
     */
    public PageResult<AdminVO> adminPage(AdminQuery query) {
        //1.准备一个空的pageResult返回对象
        PageResult<AdminVO> voPages = new PageResult<>();
        //2.调用仓储层查询数据库分页数据,返回值是PageInfo
        PageInfo<AdminPO> pageInfo = adminRepository.getAdminByPage(query);
        //3.将pageInfo中的数据封装到voPages中
        //pageNo pageSize total
        voPages.setPageNo(pageInfo.getPageNum());
        voPages.setPageSize(pageInfo.getPageSize());
        voPages.setTotal(pageInfo.getTotal());
        //4.将pageInfo中的list数据封装到voPages中,判断list是否为空
        List<AdminVO> vos = null;//初始化一个空的list
        List<AdminPO> pos = pageInfo.getList();//获取pageInfo中的list数据
        if (CollectionUtils.isNotEmpty(pos)){//如果list不为空
            vos = pos.stream().map(po->{//将list中的每个po对象转化为vo对象
                AdminVO vo = new AdminVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPages.setObjects(vos);//将vo集合设置到voPages中
        return voPages;
    }

    /**
     * 新增后台账号
     * @param adminParam
     */
    public void adminSave(AdminParam adminParam) throws BusinessException {
        //1.验证角色 是否满足 匹配ADMIN
        checkRole(Roles.ADMIN);
        //2.验证商家 businessId未必是合法数据
        checkBusinessExist(adminParam);
        //3 我们不允许电话 重复
        checkPhoneReuse(adminParam);
        //4.分装数据新增写入
        doSave(adminParam);
    }

    //保存数据 新增账号
    private void doSave(AdminParam param) {
        //前端表单 一般不会和数据库表格 完全对应
        AdminPO poParam=new AdminPO();
        BeanUtils.copyProperties(param,poParam);
        //param转化po的时候 我们要关注 accountStatus 0启用 1禁用 createTime businessId(保证 平台用户 值0)
        poParam.setAccountStatus(0);
        poParam.setCreateTime(new Date());
        poParam.setBusinessId(param.getAccountType()==0?0:param.getBusinessId());
        adminRepository.saveAdmin(poParam);
    }

    //检查电话号码是否重复
    private void checkPhoneReuse(AdminParam param) throws BusinessException {
        //1 使用电话号码 读取查询count
        Long count=adminRepository.countByPhone(param.getAccountPhone());
        //2 count>0 抛异常
        Asserts.isTrue(count>0,new BusinessException("-2","手机号已存在"));
    }

    //检查商家是否存在
    private void checkBusinessExist(AdminParam param) throws BusinessException {
        //新增的账号类型accountType=0 没有商家绑定的 肯定查不到
        //只有账号类型accountType=1 才读取 验证
        if (param.getAccountType()==1){
            //读取商家数据 用id 判断非空
            BusinessPO bizPO=businessRepository.getBusinessById(param.getBusinessId());
            Asserts.isTrue(bizPO==null,new BusinessException("-2","商家不存在"));
        }
    }

    //检查当前登录用户角色是否为管理员
    private void checkRole(Roles roles) throws BusinessException {
        //使用断言,当前登录用户角色是否为管理员,不是则抛出异常
        UserPrinciple userPrinciple = LbsSecurityContenxt.getLoginToken();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","用户认证解析失败"));
        //获取登录用户角色
        Roles loginRole = userPrinciple.getRole();
        Asserts.isTrue(loginRole!=roles,new BusinessException("-2","当前用户无权限"));
        log.info("当前用户角色：{}",loginRole);
    }
}
